#include <iostream>
#include <limits>

#include <QString>
#include <QtTest>

#include <math/MSc_Matrix4x4.h>

////////////////////////////////////////////////////////////////////////////////

using namespace std;

////////////////////////////////////////////////////////////////////////////////

class MSc_Matrix4x4Test : public QObject
{
    Q_OBJECT

public:

    MSc_Matrix4x4Test();

private Q_SLOTS:

    void testConstructor();

    void testGetTransposed();

    void testGetFrom();

    void testOperatorAssign();
    void testOperatorAddition();
    void testOperatorSubstraction();
    void testOperatorMultiplication();
    void testOperatorDivision();
    void testOperatorUnaryAddition();
    void testOperatorUnarySubstraction();
    void testOperatorUnaryMultiplication();
    void testOperatorUnaryDivision();
};

////////////////////////////////////////////////////////////////////////////////

MSc_Matrix4x4Test::MSc_Matrix4x4Test() {}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testConstructor()
{
    MSc_Matrix4x4 mtrx_1;

    QVERIFY( fabs( mtrx_1(0,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,3) ) < 10.0e-9 );

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    MSc_Matrix4x4 mtrx_2( mtrx_1 );

    QVERIFY( fabs( mtrx_2(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,1) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,2) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,3) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,0) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,2) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,0) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,1) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,3) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,0) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,1) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,2) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,3) - 16.0 ) < 10.0e-9 );

    MSc_Matrix4x4 mtrx_3( &mtrx_1 );

    QVERIFY( fabs( mtrx_3(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,1) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,2) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,3) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,0) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,2) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,0) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,1) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,3) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,0) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,1) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,2) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,3) - 16.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testGetTransposed()
{
    MSc_Matrix4x4 mtrx_1;

    //  1,  2,  3,  4
    //  5,  6,  7,  8
    //  9, 10, 11, 12
    // 13, 14, 15, 16

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    MSc_Matrix4x4 mtrx_2 = mtrx_1.getTransposed();

    // 1,  5,  9, 13
    // 2,  6, 10, 14
    // 3,  7, 11, 15
    // 4,  8, 12, 16

    QVERIFY( fabs( mtrx_2(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,1) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,2) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,3) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,0) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,2) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,3) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,0) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,1) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,3) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,0) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,1) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,2) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,3) - 16.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testGetFrom()
{
    MSc_Matrix4x4 mtrx_1;

    double array[ 16 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };

    mtrx_1 = MSc_Matrix4x4::getFrom( array );

    QVERIFY( fabs( mtrx_1(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,1) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,2) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,3) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,0) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,2) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,0) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,1) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,3) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,0) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,1) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,2) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,3) - 16.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorAssign()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_2 = mtrx_1;

    QVERIFY( fabs( mtrx_2(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,1) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,2) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,3) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,0) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,2) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,0) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,1) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,3) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,0) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,1) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,2) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,3) - 16.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorAddition()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;
    MSc_Matrix4x4 mtrx_3;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_2(0,0) =  1.0;
    mtrx_2(0,1) =  2.0;
    mtrx_2(0,2) =  3.0;
    mtrx_2(0,3) =  4.0;
    mtrx_2(1,0) =  5.0;
    mtrx_2(1,1) =  6.0;
    mtrx_2(1,2) =  7.0;
    mtrx_2(1,3) =  8.0;
    mtrx_2(2,0) =  9.0;
    mtrx_2(2,1) = 10.0;
    mtrx_2(2,2) = 11.0;
    mtrx_2(2,3) = 12.0;
    mtrx_2(3,0) = 13.0;
    mtrx_2(3,1) = 14.0;
    mtrx_2(3,2) = 15.0;
    mtrx_2(3,3) = 16.0;

    mtrx_3 = mtrx_1 + mtrx_2;

    QVERIFY( fabs( mtrx_3(0,0) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,1) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,2) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,0) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,1) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,2) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,3) - 16.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,0) - 18.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,1) - 20.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,2) - 22.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,3) - 24.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,0) - 26.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,1) - 28.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,2) - 30.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,3) - 32.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorSubstraction()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;
    MSc_Matrix4x4 mtrx_3;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_2(0,0) =  1.0;
    mtrx_2(0,1) =  2.0;
    mtrx_2(0,2) =  3.0;
    mtrx_2(0,3) =  4.0;
    mtrx_2(1,0) =  5.0;
    mtrx_2(1,1) =  6.0;
    mtrx_2(1,2) =  7.0;
    mtrx_2(1,3) =  8.0;
    mtrx_2(2,0) =  9.0;
    mtrx_2(2,1) = 10.0;
    mtrx_2(2,2) = 11.0;
    mtrx_2(2,3) = 12.0;
    mtrx_2(3,0) = 13.0;
    mtrx_2(3,1) = 14.0;
    mtrx_2(3,2) = 15.0;
    mtrx_2(3,3) = 16.0;

    mtrx_3 = mtrx_1 - mtrx_2;

    QVERIFY( fabs( mtrx_3(0,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(0,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(1,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(2,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_3(3,3) ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorMultiplication()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_2 = 2.0 * mtrx_1;

    QVERIFY( fabs( mtrx_2(0,0) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,1) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,2) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,0) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,1) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,2) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,3) - 16.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,0) - 18.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,1) - 20.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,2) - 22.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,3) - 24.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,0) - 26.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,1) - 28.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,2) - 30.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,3) - 32.0 ) < 10.0e-9 );

    mtrx_2 = mtrx_1 * mtrx_1;

    QVERIFY( fabs( mtrx_2(0,0) -  90.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,1) - 100.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,2) - 110.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,3) - 120.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,0) - 202.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,1) - 228.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,2) - 254.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,3) - 280.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,0) - 314.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,1) - 356.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,2) - 398.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,3) - 440.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,0) - 426.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,1) - 484.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,2) - 542.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,3) - 600.0 ) < 10.0e-9 );

    MSc_Vector4 vect_1;
    MSc_Vector4 vect_2;

    vect_1(0) = 1.0;
    vect_1(1) = 2.0;
    vect_1(2) = 3.0;
    vect_1(3) = 4.0;

    vect_2 = mtrx_1 * vect_1;

    QVERIFY( fabs( vect_2(0) -  30.0 ) < 10.0e-9 );
    QVERIFY( fabs( vect_2(1) -  70.0 ) < 10.0e-9 );
    QVERIFY( fabs( vect_2(2) - 110.0 ) < 10.0e-9 );
    QVERIFY( fabs( vect_2(3) - 150.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorDivision()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;

    mtrx_1(0,0) =  2.0;
    mtrx_1(0,1) =  4.0;
    mtrx_1(0,2) =  6.0;
    mtrx_1(0,3) =  8.0;
    mtrx_1(1,0) = 10.0;
    mtrx_1(1,1) = 12.0;
    mtrx_1(1,2) = 14.0;
    mtrx_1(1,3) = 16.0;
    mtrx_1(2,0) = 18.0;
    mtrx_1(2,1) = 20.0;
    mtrx_1(2,2) = 22.0;
    mtrx_1(2,3) = 24.0;
    mtrx_1(3,0) = 26.0;
    mtrx_1(3,1) = 28.0;
    mtrx_1(3,2) = 30.0;
    mtrx_1(3,3) = 32.0;

    mtrx_2 = mtrx_1 / 2.0;

    QVERIFY( fabs( mtrx_2(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,1) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,2) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(0,3) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,0) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,2) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(1,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,0) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,1) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(2,3) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,0) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,1) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,2) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_2(3,3) - 16.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorUnaryAddition()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_2(0,0) =  1.0;
    mtrx_2(0,1) =  2.0;
    mtrx_2(0,2) =  3.0;
    mtrx_2(0,3) =  4.0;
    mtrx_2(1,0) =  5.0;
    mtrx_2(1,1) =  6.0;
    mtrx_2(1,2) =  7.0;
    mtrx_2(1,3) =  8.0;
    mtrx_2(2,0) =  9.0;
    mtrx_2(2,1) = 10.0;
    mtrx_2(2,2) = 11.0;
    mtrx_2(2,3) = 12.0;
    mtrx_2(3,0) = 13.0;
    mtrx_2(3,1) = 14.0;
    mtrx_2(3,2) = 15.0;
    mtrx_2(3,3) = 16.0;

    mtrx_1 += mtrx_2;

    QVERIFY( fabs( mtrx_1(0,0) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,1) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,2) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,0) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,1) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,2) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,3) - 16.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,0) - 18.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,1) - 20.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,2) - 22.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,3) - 24.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,0) - 26.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,1) - 28.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,2) - 30.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,3) - 32.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorUnarySubstraction()
{
    MSc_Matrix4x4 mtrx_1;
    MSc_Matrix4x4 mtrx_2;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_2(0,0) =  1.0;
    mtrx_2(0,1) =  2.0;
    mtrx_2(0,2) =  3.0;
    mtrx_2(0,3) =  4.0;
    mtrx_2(1,0) =  5.0;
    mtrx_2(1,1) =  6.0;
    mtrx_2(1,2) =  7.0;
    mtrx_2(1,3) =  8.0;
    mtrx_2(2,0) =  9.0;
    mtrx_2(2,1) = 10.0;
    mtrx_2(2,2) = 11.0;
    mtrx_2(2,3) = 12.0;
    mtrx_2(3,0) = 13.0;
    mtrx_2(3,1) = 14.0;
    mtrx_2(3,2) = 15.0;
    mtrx_2(3,3) = 16.0;

    mtrx_1 -= mtrx_2;

    QVERIFY( fabs( mtrx_1(0,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,3) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,0) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,1) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,2) ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,3) ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorUnaryMultiplication()
{
    MSc_Matrix4x4 mtrx_1;

    mtrx_1(0,0) =  1.0;
    mtrx_1(0,1) =  2.0;
    mtrx_1(0,2) =  3.0;
    mtrx_1(0,3) =  4.0;
    mtrx_1(1,0) =  5.0;
    mtrx_1(1,1) =  6.0;
    mtrx_1(1,2) =  7.0;
    mtrx_1(1,3) =  8.0;
    mtrx_1(2,0) =  9.0;
    mtrx_1(2,1) = 10.0;
    mtrx_1(2,2) = 11.0;
    mtrx_1(2,3) = 12.0;
    mtrx_1(3,0) = 13.0;
    mtrx_1(3,1) = 14.0;
    mtrx_1(3,2) = 15.0;
    mtrx_1(3,3) = 16.0;

    mtrx_1 *= 2.0;

    QVERIFY( fabs( mtrx_1(0,0) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,1) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,2) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,0) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,1) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,2) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,3) - 16.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,0) - 18.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,1) - 20.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,2) - 22.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,3) - 24.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,0) - 26.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,1) - 28.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,2) - 30.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,3) - 32.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_Matrix4x4Test::testOperatorUnaryDivision()
{
    MSc_Matrix4x4 mtrx_1;

    mtrx_1(0,0) =  2.0;
    mtrx_1(0,1) =  4.0;
    mtrx_1(0,2) =  6.0;
    mtrx_1(0,3) =  8.0;
    mtrx_1(1,0) = 10.0;
    mtrx_1(1,1) = 12.0;
    mtrx_1(1,2) = 14.0;
    mtrx_1(1,3) = 16.0;
    mtrx_1(2,0) = 18.0;
    mtrx_1(2,1) = 20.0;
    mtrx_1(2,2) = 22.0;
    mtrx_1(2,3) = 24.0;
    mtrx_1(3,0) = 26.0;
    mtrx_1(3,1) = 28.0;
    mtrx_1(3,2) = 30.0;
    mtrx_1(3,3) = 32.0;

    mtrx_1 /= 2.0;

    QVERIFY( fabs( mtrx_1(0,0) -  1.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,1) -  2.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,2) -  3.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(0,3) -  4.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,0) -  5.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,1) -  6.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,2) -  7.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(1,3) -  8.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,0) -  9.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,1) - 10.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,2) - 11.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(2,3) - 12.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,0) - 13.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,1) - 14.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,2) - 15.0 ) < 10.0e-9 );
    QVERIFY( fabs( mtrx_1(3,3) - 16.0 ) < 10.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

QTEST_APPLESS_MAIN(MSc_Matrix4x4Test)

////////////////////////////////////////////////////////////////////////////////

#include "tst_msc_matrix4x4test.moc"
